<script type="text/javascript">
//Proxy 与 Reflect 是 ES6 为了操作对象引入的 API 。
//1.Proxy 可以对目标对象的读取、函数调用等操作进行拦截，然后进行操作处理。它不直接操作对象，而是像代理模式，通过对象的代理对象进行操作，在进行这些操作时，可以添加一些需要的额外操作。
//2.Reflect 可以用于获取目标对象的行为，它与 Object 类似，但是更易读，为操作对象提供了一种更优雅的方式。它的方法与 Proxy 是对应的。

//1. Proxy
//一个 Proxy 对象由两个部分组成： target 目标对象 、 handler 是一个对象,声明了代理 target 的指定行为。
let target = {
    name: 'Tom',
    age: 24
}
let handler = {
    get: function(target, key) {
        document.write('getting '+key);
        return target[key]; // 不是target.key
    },
    set: function(target, key, value) {
    	document.write('<br> ');
        document.write('setting '+key);
        target[key] = value;
    }
}
let proxy = new Proxy(target, handler)
proxy.name     // 实际执行 handler.get
document.write('<br> ');
document.write(' : '+proxy.name);
proxy.age = 25 // 实际执行 handler.set

document.write('<br> ');
document.write(' : '+proxy.age);


document.write('<br><br><br>'); 

let exam ={
    name: "Tom",
    age: 24
}
let proxy1 = new Proxy(exam, {
  get(target, propKey, receiver) {
    console.log('Getting ' + propKey[0]);
    return target[propKey];
  }
})
proxy1.name 
document.write('<br> ');
document.write('Getting : '+proxy1.name);


document.write('<br><br><br>'); 

//get() 方法可以继承。
let proxy2 = new Proxy({}, {
  get(target2, propKey2, receiver2) {
      // 实现私有属性读取保护
      if(propKey2[0] === '_'){
          throw new Erro(`Invalid attempt to get private     "${propKey2}"`);
      }
      console.log('Getting ' + propKey2);
      return target2[propKey2];
  }
});
 
let obj = Object.create(proxy);
obj.name
document.write('<br> ');
document.write('Getting : '+obj.name);

// Getting name


document.write('<br><br><br>'); 
//用于拦截 target 对象上的 propKey 的赋值操作。
let validator = {
    set: function(obj, prop, value) {
        if (prop === 'age') {
            if (!Number.isInteger(value)) {
                throw new TypeError('The age is not an integer');
            }
            if (value > 200) {
                throw new RangeError('The age seems invalid');
            }
        }
        // 对于满足条件的 age 属性以及其他属性，直接保存
        obj[prop] = value;
    }
};
let proxy3= new Proxy({}, validator)
proxy3.age = 100;
proxy3.age           // 100
document.write('<br> ');
document.write('Getting : '+proxy3.age);
//proxy3.age = 'oppps' // 报错
//proxy3.age = 300     // 报错



document.write('<br><br><br>'); 
//2.Reflect

let exam1 = {
    name: "Tom",
    age: 24,
    get info(){
        return this.name + this.age;
    }
}
Reflect.get(exam1, 'name'); // "Tom"
document.write(Reflect.get(exam1, 'name'));
document.write(exam1['name']);
</script>